# python库打包分发setup.py编写指南
# http://coolpython.net/python_senior/project/op_py_setup_install.html
import hashlib
import os
from io import BytesIO
from flask import (
    request,
    make_response,
    jsonify,
    session as se, send_from_directory, Response, send_file, current_app, g,

)
from sqlalchemy import or_, and_
from werkzeug.exceptions import RequestEntityTooLarge
from werkzeug.utils import secure_filename

from exts import session, insp
from exts.captcha.Captcha import Captcha
from exts.auth import login_required
from exts.excel import Excel
from exts.makeToken import create_token
from exts.role import permission_required
from exts.send_file import allowed_file
from exts.sign import login_sign
from exts.xjson import json_success, json_error
from settings import UPLOAD_URL, PROFILE_URL, ALLOWED_SIZE
from . import user_bp
from apps.user.models import User, Files, Role, Role_User, Permission
from flask import Flask, send_file

from pathlib import Path


@user_bp.route('/user_center', methods=['GET', 'POST'])
@login_required
def user_center():
    if request.method == 'GET':
        display_list = []
        user_list = session.query(User).filter(User.isdelete == 1)
        display = [user for user in user_list if user.isdelete == 1]
        for user in display:
            d = {'id': user.id, 'username': user.username, 'phone': user.phone, 'email': user.email}
            display_list.append(d)
        return json_success(message='success', data={'user': display_list})


@user_bp.route('/search', methods=['GET', 'POST'])
@login_required
def search():
    if request.method == 'GET':
        keyword = request.args.get('search')
        user_list = session.query(User).filter(
            or_(User.username.contains(keyword),
                User.phone.contains(keyword),
                User.email.contains(keyword))).all()
        for item in user_list:
            if keyword in ['$', '%', '^', '&', '*', '~']:
                return json_error(message='输入数据不合法，请重新输入', data={})
            if keyword:
                d = {'id': item.id, 'username': item.username, 'phone': item.phone,
                     'email': item.email}
                return json_success(message='success', data={'user': d})
            if not keyword:
                return json_error(message='搜索不能为空,请输入姓名或手机号码或邮箱', data={})


@user_bp.route('/register', methods=['GET', 'POST'], endpoint='register')
def register():
    """
    注册功能
    :return:
    """
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        repassword = request.form['repassword']
        phone = request.form['phone']
        if not username:
            return json_error(message='账号不能为空，输入账号', data={})
        if not password:
            return json_error(message='密码不能为空，输入密码', data={})
        if not repassword:
            return json_error(message='确认密码不能为空，输入确认密码', data={})
        if password != repassword:
            return json_error(message='密码输入不一致，请重新输入', data={})
        if not phone:
            return json_error(message='手机号不能为空，请输入手机号', data={})
        user_list = session.query(User).filter().all()
        phones = []
        for tel in user_list:
            phones.append(tel.phone)
        if phone in phones:
            return json_error(message='手机号码已存在，请重新输入', data={})
        else:
            user = User(username=username,
                        password=hashlib.sha256(password.encode('utf-8')).hexdigest(),
                        phone=phone)
            session.add(user)
            session.commit()
            return json_success(message='注册成功', data={'username': username})


@user_bp.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        h_password = hashlib.sha256(password.encode('utf-8')).hexdigest()
        if not username or not password:
            data = json_error(message='用户名或密码不能为空，请输入...', data={})
            response = make_response(data)
            response.headers["Content-Type"] = "application/json;charset=UTF-8"
            return response
        data = session.query(User).filter(and_(User.username == username, User.isdelete == 1)).scalar()
        if not data:
            return json_error(message='用户不存在，请先进行注册', data={})
        data = session.query(User).filter(User.username == username).all()
        for pwd in data:
            if pwd.password != h_password:
                data = json_error(message='用户名或密码错误，请重新输入', data={})
                response = make_response(data)
                response.headers["Content-Type"] = "application/json;charset=UTF-8"
                return response
            else:
                # 发送信号
                login_sign.send(username=username)
                # 生成token。需要前端将token存储在headers中，再进行验证
                token = create_token(username)
                se['username'] = username
                login_session = se.get('username')
                data = json_success(message='登录成功', data={'token': token, 'session': login_session})
                response = make_response(data)
                response.headers["Content-Type"] = "application/json;charset=UTF-8"

                se.permanent = True  # 默认为False，设置为true，则会存储31天
                return response


@user_bp.route('/update', methods=['GET', 'POST'], endpoint='update')
@login_required
def update():
    if request.method == 'GET':
        id = request.args.get('id')
        user = User.query.get(id)
        return jsonify({'user': user})
    if request.method == 'POST':
        id = request.form.get('id')
        username = request.form.get('username')
        phone = request.form.get('phone')
        email = request.form.get('email')
        user = session.query(User).filter(User.id == id).first()
        user.username = username
        user.phone = phone
        user.email = email
        session.commit()
        return json_success(message='修改成功',
                            data={'username': user.username,
                                  'phone': user.phone,
                                  'email': user.email})


@user_bp.route('/delete', methods=['GET', 'POST'])
@login_required
def delete():
    """
    永久删除
    """
    if request.method == 'POST':
        id = request.form.get('id')
        user = session.query(User).get(id)
        if not user:
            return json_error(message='删除数据不存在，请先进行确认', data={})
        else:
            session.delete(user)
            session.commit()
            return json_success(message='删除成功', data=user.username)


@user_bp.route('/faker_delete', methods=['GET', 'POST'])
@login_required
def faker_del():
    """
    标记删除
    """
    if request.method == 'POST':
        id = request.form.get('id')
        user = session.query(User).get(id)
        if not user or user.isdelete == 0:
            return json_error(message='删除数据不存在，请先进行确认', data={})
        if user or user.isdelete == 1:
            user.isdelete = 0
            session.commit()
            return json_success(message='删除成功', data=user.username)


@user_bp.route('/mod_pwd', methods=['GET', 'POST'])
@login_required
def mod_pwd():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        new_password = request.form.get('new_password')
        user = session.query(User).filter(User.username == username).first()
        # 通过sha256加密
        old_password = hashlib.sha256(password.encode('utf-8')).hexdigest()
        new_password = hashlib.sha256(new_password.encode('utf-8')).hexdigest()
        if user.password == old_password:
            user.password = new_password
            user.username = username
            session.commit()
            return json_success(message='密码修改成功')
        if user.password != old_password:
            return json_error(message='旧密码输入错误，请重新输入', data={})


@user_bp.route('/logout', methods=['GET', 'POST'])
@login_required
def logout():
    # 删除session
    se.clear()
    return json_success(message='退出成功，欢迎下次再来！')


@user_bp.route('/graph_captcha', methods=['GET', 'POST'])
def graph_captcha():
    """
    生成验证码
     读写字节串使用BytesIO，读写字符串使用StringIO
    """
    if request.method == 'GET':
        text, image = Captcha.gene_graph_captcha()
        out = BytesIO()
        image.save(out, 'png')
        out.seek(0)
        res = make_response(out.read())
        res.content_type = 'image/png'
        return res


@user_bp.route('upload', methods=['GET', 'POST'])
@login_required
def upload():
    if request.method == 'POST':
        obj = request.files.get('pic')
        # fspath = os.path.abspath(obj.filename+UPLOAD_URL)
        # print('###:',fspath)
        # if os.path.getsize(fspath) > ALLOWED_SIZE:
        #     return json_error(message='文件上传大于10M,请重新选择上传')
        if obj.filename == '':
            return json_error(message='您未选择上传对象，请先选择...')
        if obj and allowed_file(obj.filename):
            filename = secure_filename(obj.filename)
        else:
            return json_error(message="只允许上传txt,pdf,png,jpg,jpeg,gif格式的文件")
        if session.query(Files).filter(Files.filename.contains(filename)).all():
            return json_error(message='文件名称重复，请重新上传')
        if obj and allowed_file(filename):
            img_url = UPLOAD_URL + os.path.join('\\') + filename
            obj.save(img_url)  # 保存图片
            photos = Files(path=img_url, filename=filename)
            session.add(photos)
            session.commit()
        return json_success(message='图片(附件)、视频上传成功')


@user_bp.route('download_pic', methods=['GET', 'POST'])
@login_required
def download_pic():
    if request.method == 'GET':
        filename = request.args.get('filename')
        # 写法一
        files = session.query(Files).filter(Files.filename == filename).scalar()
        return send_file(files.path, as_attachment=True, attachment_filename=filename)
        # 写法二
        # return send_from_directory(directory=UPLOAD_URL, filename=filename)


@user_bp.route('add_email', methods=['GET', 'POST'])
@login_required
def add_email():
    if request.method == 'POST':
        id = request.form.get('id')
        user = session.query(User).get(id)
        email = request.form.get('email')
        if not user.email:
            user.email = email
            session.commit()
            return json_success(message='添加邮箱成功', data={'email': user.email})
        else:
            user.email = email
            session.add(user)
            session.commit()
            return json_success(message='邮箱修改成功', data={'email': user.email})


@user_bp.route('add_profile', methods=['GET', 'POST'])
@login_required
def add_profile():
    if request.method == 'POST':
        id = request.form.get('id')
        user = session.query(User).get(id)
        icon = request.files.get('icon')
        if not user.icon:
            icon_url = PROFILE_URL + os.path.join('\\') + icon.filename
            icon.save(icon_url)  # 保存头像
            user.icon = icon_url
            session.commit()
            return json_success(message='头像添加成功')
        else:
            icon_url = PROFILE_URL + os.path.join('\\') + icon.filename
            icon.save(icon_url)
            user.icon = icon_url
            session.add(user)
            session.commit()
            return json_success('头像修改成功')


@user_bp.route('add_role', methods=['GET', 'POST'])
@login_required
def add_role():
    """
    1:访问者 ：可以修改个人信息
    23:运营：管理帖子，评论，前台用户
    63:管理员：拥有本系统所有权限
    255:开发者：开发人员专用
    """
    if request.method == 'POST':
        name = request.form.get('name')
        desc = request.form.get('desc')
        permissions = request.form.get('permissions')
        if session.query(Role).filter(Role.name.contains(name)).all():
            return json_error(message='角色重复，请重新添加')
        else:
            role = Role(name=name, desc=desc, permissions=permissions)
            session.add(role)
            session.commit()
        return json_success(message='用户角色添加成功', data=role.name)


@user_bp.route('export_by_excle', methods=['GET', 'POST'])
# @login_required
def export_by_execle():
    # 获取数据库名
    # insp.get_schema_names()
    # 获取数据库下的表名
    # insp.get_table_names(schema='flask01')
    # 获取数据表列名
    columns = insp.get_columns('t_user', schema='flask01')
    col = [column['name'] for column in columns]
    user_list = session.query(User).all()
    # 获取字节流
    output = Excel().export(columns=col, values=user_list)
    return send_file(output, attachment_filename="用户台账.xlsx",
                     as_attachment=True)


@user_bp.route('role_auth', methods=['GET', 'POST'])
@login_required
def set_role():
    """
    给用户设置角色
    """
    username = request.form.get('username')
    name = request.form.get('name')
    users = session.query(User).filter(User.username == username).all()
    roles = session.query(Role).filter(Role.name == name).all()
    for u, r in zip(users, roles):
        role_user = Role_User(user_id=u.id, role_id=r.id)
        item = session.query(Role_User).filter(and_(Role_User.user_id == u.id, Role_User.role_id == r.id)).scalar()
        if item is None:
            session.add(role_user)
            session.commit()
            return json_success(message='角色授权成功')
        return json_error(message='角色已授权')
